<template>
  <div class="FL-container getting-started">
    <!-- 辅助工具栏 -->
    <Control class="demo-control" v-if="lf.container" :lf="lf as LogicFlow" @catData="$_catData" @saveModel="$_saveModel"></Control>
    <!-- 画布 -->
    <div class="app-content" ref="logicFlowContainerRef"></div>
    <!-- 属性面板 -->
    <el-drawer title="设置节点属性" v-model="dialogVisible" direction="rtl" size="900px" :before-close="closeDialog">
      <PropertyDialog v-if="dialogVisible" :nodeData="clickNode" :lf="lf as LogicFlow" @setPropertiesFinish="closeDialog"></PropertyDialog>
    </el-drawer>
    <!-- 数据查看面板 -->
    <el-dialog title="数据" v-model="dataVisible" width="50%">
      <DataDialog :graphData="graphData"></DataDialog>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import LogicFlow from "@logicflow/core";
import {DndPanel, Menu, MiniMap, SelectionSelect} from '@logicflow/extension';
import "@logicflow/core/lib/style/index.css";
import '@logicflow/extension/lib/style/index.css';
import {onMounted, ref} from "vue";
import Control from "/@/components/gFlow/Control.vue"
import {setPatternItems, setTheme} from "/@/components/gFlow/config";

import {
  registerEnd,
  registerStart,
  registerConcurrent,
  registerPush,
  registerCondition,
  registerUserTask
} from "/@/components/gFlow/registerNode";

import { Snapshot } from "@logicflow/extension";
import PropertyDialog from "/@/components/gFlow/propertySetting/PropertyDialog.vue";
import DataDialog from "/@/components/gFlow/DataDialog.vue";
import {useRoute} from "vue-router";
import {ElMessage} from "element-plus";
import {getNodeData, saveModeNode} from "/@/api/flow/flowModel";
import {
  FlowCheckRuleDept,
  FlowCheckRuleDeptLeader, FlowCheckRulePost,
  FlowCheckRuleRole,
  FlowCheckRuleUser
} from "/@/components/gFlow/consts";
import GraphConfigData = LogicFlow.GraphConfigData;
defineOptions({ name: "logicFlowDesign"})
const route = useRoute()
const modelId = ref(0)
const logicFlowContainerRef = ref()
const lf = ref<LogicFlow>({} as LogicFlow)
const dataVisible = ref(false)
const graphData = ref<GraphConfigData>()
const addPanelStyle = ref({
  top: '0',
  left: '0',
})
const showAddPanel = ref(false)
const addClickNode = ref<any>()
const clickNode = ref({})
const dialogVisible = ref(false)
const moveData = ref({})
onMounted(()=>{
  if (route.query.id){
    modelId.value = parseInt(route.query.id as string)
  }else{
    ElMessage.error('参数错误');
    return
  }
  lf.value = new LogicFlow({
    container: logicFlowContainerRef.value,
    grid: true,
    plugins: [DndPanel, SelectionSelect,Snapshot,Menu, MiniMap],
    pluginsOptions: {
      miniMap: {
        isShowHeader: false,
        isShowCloseIcon: true,
        headerTitle: 'MiniMap'
      }
    }
  })
  registerNode()
  initLF()
})
//注册节点信息
const registerNode = ()=>{
  const logicFlow = lf.value as LogicFlow
  registerStart(logicFlow)
  registerEnd(logicFlow)
  registerConcurrent(logicFlow)
  registerPush(logicFlow)
  registerCondition(logicFlow)
  registerUserTask(logicFlow)
}

const initLF=()=>{
  const logicFlow = lf.value as LogicFlow;
  setPatternItems(logicFlow)
  setTheme(logicFlow)
  $_render()
  $_LfEvent()
}
const $_render = ()=>{
  //获取节点数据
  getNodeData(modelId.value).then((res:any)=>{
    const nodes = (res.data.nodes??[]).map((item:any)=>{
      const node = {
        id: item.nodeId,
        type: item.nodeType,
        x: item.nodePosition.x,
        y: item.nodePosition.y,
        text: item.nodeText??{},
        properties: {
          text: item.nodeText?.value,
          actionRule: item.nodeActionRule,
          approveRule: item.nodeRule,
          notice: item.notice ?? [],
          rollback: item.rollback,
          nodeExt: item.nodeExt??[]
        }
      }
      setReceiver(node,item.nodeReceiver)
      return node
    })
    const edges = (res.data.edges??[]).map((item:any)=>{
      return {
        id: item.id,
        type: item.lineType,
        sourceNodeId: item.sourceNodeId,
        targetNodeId: item.targetNodeId,
        startPoint:item.startPoint,
        endPoint:item.endPoint,
        properties: item.properties,
        pointsList: item.pointsList,
        text:item.text
      }
    })
    lf.value.render({nodes,edges});
    $_LfEvent();
  })
}
const setReceiver = (node:any,receivers:Array<string>)=>{
  switch(node.properties.actionRule){
    case FlowCheckRuleRole://角色
      node.properties.roleIds = receivers
      break
    case FlowCheckRuleDept://部门
    case FlowCheckRuleDeptLeader://部门负责人
      node.properties.deptIds = receivers
      break
    case FlowCheckRuleUser://指定人员
      node.properties.userIds = receivers
      break
    case FlowCheckRulePost://岗位
      node.properties.postIds = receivers
  }
}
const $_catData = () => {
  graphData.value = lf.value.getGraphData() as GraphConfigData;
  dataVisible.value = true;
}
const $_saveModel = ()=>{
  const data = lf.value.getGraphData() as any
  const nodes = data.nodes.map((item:any)=>{
    return {
      nodeId:item.id,
      modelId:modelId.value,
      nodeType:item.type,
      nodePosition:{x:item.x,y:item.y},
      nodeText:item.text,
      nodeActionRule:item.properties?.actionRule,
      nodeReceiver: getNodeReceiver(item.properties?.actionRule,item),
      nodeRule:item.properties?.approveRule,
      notice:item.properties?.notice,
      rollback:item.properties?.rollback,
      nodeExt:item.properties?.nodeExt
    }
  })
  const edges = data.edges.map((item:any)=>{
    return {
      modelId:modelId.value,
      lineType:item.type,
      sourceNodeId:item.sourceNodeId,
      targetNodeId:item.targetNodeId,
      startPoint:item.startPoint,
      endPoint:item.endPoint,
      properties:item.properties,
      text:item.text,
      pointsList:item.pointsList
    }
  })
  const postData = {
    modelId:modelId.value,
    nodes:nodes,
    edges:edges
  }
  saveModeNode(postData).then((res:any)=>{
    if(res.code===0){
      ElMessage.success('保存成功');
    }else{
      ElMessage.error(res.data.message);
    }
  })
}
const $_LfEvent=()=>{
  const logicFlow = lf.value as LogicFlow;
  logicFlow.on('node:click', (data) => {
    console.log('node:click', data);
    clickNode.value = data.data;
    dialogVisible.value = true;
  })
  logicFlow.on('edge:click', ({ data }) => {
    console.log('edge:click', data);
    //this.$data.clickNode = data;
    //this.$data.dialogVisible = true;
  });
  logicFlow.on('element:click', () => {
    hideAddPanel();
  });
  logicFlow.on('edge:add', ({ data }) => {
    console.log('edge:add', data);
  });
  logicFlow.on('node:mousemove', ({ data }) => {
    console.log('node:mousemove');
    moveData.value = data;
  });
  logicFlow.on('blank:click', () => {
    hideAddPanel();
  });
  logicFlow.on('connection:not-allowed', (data) => {
    console.log('connection:not-allowed',data)
  });
  logicFlow.on('node:mousemove', () => {
    console.log('on mousemove');
  });
}
const hideAddPanel = () => {
  showAddPanel.value = false;
  addPanelStyle.value.top = '0';
  addPanelStyle.value.left = '0';
  addClickNode.value = null;
}
const closeDialog = () => {
  dialogVisible.value = false;
}
const getNodeReceiver = (rule:number,item:any)=>{
  switch(rule){
    case FlowCheckRuleRole://角色
      return item.properties.roleIds
    case FlowCheckRuleDept://部门
    case FlowCheckRuleDeptLeader://部门负责人
      return item.properties.deptIds
    case FlowCheckRuleUser://指定人员
      return item.properties.userIds
    case FlowCheckRulePost://岗位
      return item.properties.postIds
  }
  return []
}
</script>

<style scoped lang="scss">
.FL-container {
  width: 100%;
  overflow: hidden;
  .app-content {
    height: calc(100vh - 120px);
  }
}
.demo-control{
  position: absolute;
  top: 20px;
  right: 50px;
  z-index: 2;
}
</style>
